//
//  HttpTools.swift
//  sss
//
//  Created by hrrMac on 2020/6/1.
//  Copyright © 2020 hrrMac. All rights reserved.
//

import Foundation
import KakaJSON
import Alamofire

let ROOTURL = "http://106.53.253.77:8082/"

// MARK: - http请求状态
enum HttpStatus {
    case success
    case netWorkError
    case serviceError
    case otherError  //其他操作，比如没有填写url
}


// MARK: - 返回参数
 public struct HttpRespons {
    let status   : HttpStatus
    let msg      : String
    let response : Dictionary<String, Any>
    let dataArr  : Array<Any>
}



// MARK: - 数据请求根
public func HTTPRequest(
    _ url      : String,
    method     : HTTPMethod = .post,
    parameters : [String: Any],
    result     : @escaping ((_ response:HttpRespons)->Void),
    model      : Convertible.Type? )
{
    HTTPRequest(url, method: method, encoding: JSONEncoding.default, parameters: parameters, result: result, model: model)
}


public func HTTPRequest(
    _ url      : String,
    method     : HTTPMethod = .post,
    encoding   : ParameterEncoding = JSONEncoding.default,
    parameters : [String: Any],
    result     : @escaping ((_ response:HttpRespons)->Void),
    model      : Convertible.Type? )
{
    assert(!url.isEmpty,"url为空")
//    var headers = SessionManager.defaultHTTPHeaders //HTTPHeaders.default
//    headers["token"] = "";
    let headers: HTTPHeaders = [
        "Authorization": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==",
        "Content-type":"application/json;charset=utf-8",
        "Accept":"application/json",
        "token": ""
    ]
    
    
    AF.request(url, method: method, parameters: parameters, encoding: encoding, headers: headers).responseData { (response) in
        printResponseData(response)
        switch response.result{
        case .success:
            if let items = response.value as? Parameters{
                judgAlamofirDataResultWithKakaJSONClass(response: items, model: model, result: result)
            }else{
                assert(false, "数据格式错误,返回的不是JSON对象数据")
                let res = HttpRespons(status: .netWorkError, msg: "数据格式错误,返回的不是JSON对象数据", response: [:], dataArr: [])
                result(res)
            }
            
        case .failure(let error):
            let res = HttpRespons(status: .netWorkError, msg: error.localizedDescription, response: [:], dataArr: [])
            result(res)
        }
    }
}



// MARK: - POST


/// POST请求(result 使用与列表封装!!!!!!!!闭包里面操作一定要[weak self]!!!!!!!!)
/// - Parameters:
///   - url: 路径，不需要带根路径会自动拼接
///   - parameters: 参数
///   - result: 返回结果的回调
///   - model: 要解析的模型
public func HTTPPOST(
    _ url      : String,
    parameters : [String: Any],
    result     : @escaping ((_ response:HttpRespons)->Void),
    model      : Convertible.Type?)
{
    HTTPRequest(ROOTURL + url, parameters: parameters, result: result, model: model)
}

 
/// POST请求(success and failure)(!!!!!!!!闭包里面操作一定要[weak self]!!!!!!!!)
/// - Parameters:
///   - url: 路径，不需要带根路径
///   - parameters: 参数
///   - success: 请求成功的回调
///   - failure: 请求失败的回调（接口返回错误或者网络错误都会走此回调）
///   - model: 要解析的模型
public func HTTPPOST(
    _ url      : String,
    parameters : [String: Any],
    success    : (@escaping(_ response:HttpRespons)->Void),
    failure    : (@escaping(_ error: String) -> Void),
    model      : Convertible.Type?)
{
    HTTPRequest(ROOTURL + url , parameters: parameters, result: { (response) in
        if response.status == .success {
            success(response)
        }else{
            failure(response.msg)
        }
    }, model: model)
}


// MARK: - GET


/// GET请求(result 使用与列表封装)
/// - Parameters:
///   - url: 路径，不需要带根路径会自动拼接
///   - parameters: 参数
///   - result: 返回结果的回调
///   - model: 要解析的模型
public func HTTPGET(
    _ url      : String,
    parameters : [String: Any],
    result     : @escaping ((_ response:HttpRespons)->Void),
    model      : Convertible.Type?)
{
    HTTPRequest(ROOTURL + url,method: .get ,parameters: parameters, result: result, model: model)
}


/// GET请求(success and failure)
/// - Parameters:
///   - url: 路径，不需要带根路径
///   - parameters: 参数
///   - success: 请求成功的回调
///   - failure: 请求失败的回调（接口返回错误或者网络错误都会走此回调）
///   - model: 要解析的模型
public func HTTPGET(
    _ url      : String,
    parameters : [String: Any],
    success    : (@escaping(_ response:HttpRespons)->Void),
    failure    : (@escaping(_ error: String) -> Void),
    model      : Convertible.Type?)
{
    /// get请求iOS13以后数据不能放body里面，所以编码的时候要用 URLEncoding.default
    HTTPRequest(ROOTURL + url, method: .get,encoding: URLEncoding.default,parameters: parameters, result: { (response) in
        if response.status == .success {
            success(response)
        }else{
            failure(response.msg)
        }
    }, model: model)
}


// MARK: - PUT

/// PUT请求(success and failure)
/// - Parameters:
///   - url: 路径，不需要带根路径
///   - parameters: 参数
///   - success: 请求成功的回调
///   - failure: 请求失败的回调（接口返回错误或者网络错误都会走此回调）
///   - model: 要解析的模型
public func HTTPPUT(
    _ url      : String,
    parameters : [String: Any],
    success    : (@escaping(_ response:HttpRespons)->Void),
    failure    : (@escaping(_ error: String) -> Void),
    model      : Convertible.Type?)
{
    HTTPRequest(ROOTURL + url, method: .put,parameters: parameters, result: { (response) in
        if response.status == .success {
            success(response)
        }else{
            failure(response.msg)
        }
    }, model: model)
}


// MARK: - DEL

/// PUT请求(success and failure)
/// - Parameters:
///   - url: 路径，不需要带根路径
///   - parameters: 参数
///   - success: 请求成功的回调
///   - failure: 请求失败的回调（接口返回错误或者网络错误都会走此回调）
///   - model: 要解析的模型
public func HTTPDEL(
    _ url      : String,
    parameters : [String: Any],
    success    : (@escaping(_ response:HttpRespons)->Void),
    failure    : (@escaping(_ error: String) -> Void),
    model      : Convertible.Type?)
{
    HTTPRequest(ROOTURL + url, method: .delete,parameters: parameters, result: { (response) in
        if response.status == .success {
            success(response)
        }else{
            failure(response.msg)
        }
    }, model: model)
}



// MARK: - 数据处理
public func judgAlamofirDataResultWithKakaJSONClass(
    response : Parameters,
    model    : Convertible.Type?,
    result   : ((_ response:HttpRespons)->Void))
{
    if let code = response["code"] as? Int {
        if code == 200 {
            if model == nil {
                let res = HttpRespons(status: .success, msg: "手动解析", response: response, dataArr: [])
                result(res);
            }else{
                let res = HttpRespons(status: .success, msg: "自动解析", response: response, dataArr: dataAlaynisWithKakaJSONClass(response: response, model: model!))
                result(res)
            }
        }else{
            var msg = "Unknow error"
            if let error = response["msg"] as? String {
                msg = error
            }
            let res = HttpRespons(status: .serviceError, msg: msg, response: response, dataArr: [])
            result(res)
        }
    }else{
        assert(false,"返回code码错误，查看数据接口。或该接口不适用次方法")
    }
}


public func dataAlaynisWithKakaJSONClass(
    response : Parameters,
    model    : Convertible.Type) ->[Convertible]
{
    if let value = response["data"] {
        if value is Dictionary<String, Any> {
            let dic = value as! Dictionary<String, Any>
            let responseModel:Convertible = dic.kj.model(type: model)
            return [responseModel];
        }
        if value is Array<Any> {
            let dic = value as! Array<Any>
            let responseArr = dic.kj.modelArray(type: model)
            return responseArr as Array<Any> as! [Convertible];
        }
        let dataArr:Array = [""]
        return dataArr as! [Convertible];
    }
    assert(false,"数据层级有问题");
    return [];
}


///缓存请求下来的数据
private func autoCacheResponse(_ url: String ,response: Dictionary<String, Any>?){
    if url.isEmpty {
        return
    }
    let directoryPath: String = NSHomeDirectory() + "/Documents/AlamofireCaches/"
    
    if !FileManager.default.fileExists(atPath: directoryPath, isDirectory: nil) {
        do {
            try FileManager.default.createDirectory(atPath: directoryPath, withIntermediateDirectories: true, attributes: nil)
        } catch let error {
            print("创建缓存目录失败")
            return
        }
    }
    
    let fileName = url
    let path = directoryPath.appending(fileName)
    let dict: AnyObject = response as AnyObject
    var data: Data?
    do {
        try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
    } catch  {
        
    }
    
    if data != nil {
        let success = FileManager.default.createFile(atPath: path, contents: data, attributes: nil)
        if success {
            print("缓存成功")
        } else {
            print("缓存失败")
        }
    }
    
}

///获取缓存数据
private func resultCache(_ url: String) -> Dictionary<String, Any>?{
    let directoryPath: String = NSHomeDirectory() + "/Documents/AlamofireCaches/"
    let fileName = url
    let path = directoryPath.appending(fileName)
    let data: Data? = FileManager.default.contents(atPath: path)
    if data != nil {
        do {
            let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers)
            let dic = json as! Dictionary<String, Any>
            return dic
        } catch  {
            return nil
        }
    }
    return nil
}


private func printData(_ url: String, data: [String: Any], token: String){
    #if DEBUG
    var str = url
    for key in data.keys {
        str.append("&\(key)=\(data[key])")
    }
    str.append("&token=\(token)")
    print("=========请求参数==============\n" + str + "\n=======================")
    #endif
}


private func printResponseData(_ response: Any){
    #if DEBUG
    print("=========请求结果==============\n")
    print(response)
    print("\n=======================")
    #endif
}
